"""
主窗口 - 股票跟单软件的主界面
左右布局：配置面板(70%) + 日志面板(30%)
"""

import sys
from PyQt5.QtWidgets import (QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, 
                            QApplication, QSplitter, QStatusBar, QLabel, QMessageBox, QSystemTrayIcon)
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QThread, pyqtSlot
from PyQt5.QtGui import QIcon, QPixmap, QPainter, QColor, QFont
import logging
import os
from datetime import datetime

from gui.config_panel import ConfigPanel
from gui.log_panel import LogPanel
from utils.config_manager import ConfigManager
from utils.logger import LoggerManager
from ocr.ocr_service import OCRService


class MonitorThread(QThread):
    """监控线程"""
    
    # 信号定义
    log_message = pyqtSignal(str, str)  # 日志消息信号 (level, message)
    ocr_result = pyqtSignal(dict)  # OCR识别结果信号
    trading_signal = pyqtSignal(str, dict)  # 交易信号 (action, data)
    
    def __init__(self, config_manager, ocr_service):
        super().__init__()
        self.config_manager = config_manager
        self.ocr_service = ocr_service
        self.logger = logging.getLogger(__name__)
        
        self.running = False
        self.monitor_interval = 3  # 默认监控间隔
        
    def run(self):
        """监控主循环"""
        self.running = True
        self.log_message.emit("INFO", "开始监控股票信号")
        
        while self.running:
            try:
                # 获取当前配置
                current_area = self.config_manager.get('area.current_area')
                if not current_area:
                    self.log_message.emit("WARNING", "未设置识别区域，暂停监控")
                    self.msleep(5000)  # 等待5秒
                    continue
                
                # 获取区域坐标
                bbox = self.config_manager.get('area.bbox')
                if not bbox:
                    self.log_message.emit("ERROR", f"识别区域坐标不存在")
                    self.msleep(5000)
                    continue
                
                # 静默执行OCR识别
                # 确保OCR服务运行
                if not self.ocr_service.ensure_service_running():
                    self.log_message.emit("ERROR", "OCR服务启动失败")
                    self.msleep(10000)  # 等待10秒重试
                    continue
                
                # 执行OCR
                result = self.ocr_service.ocr_area(bbox)
                
                if result:
                    self.ocr_result.emit(result)
                    # 分析识别结果（静默）
                    self.analyze_ocr_result(result)
                else:
                    # 只在连续失败时打印警告
                    pass
                
                # 立即进行下一次OCR，保持连续识别
                
            except Exception as e:
                self.log_message.emit("ERROR", f"监控异常: {e}")
                self.msleep(5000)  # 异常时等待5秒
    
    def analyze_ocr_result(self, result):
        """分析OCR识别结果 - 静默处理，交易信号通过市场数据比对触发"""
        try:
            # 交易信号不在这里检测，而是通过市场列表数据比对来触发
            # 这里仅做静默的数据质量检查，不打印日志
            
            # 静默统计识别质量
            high_confidence_count = 0
            total_count = len(result)
            
            for key, value in result.items():
                confidence = value.get('score', 0)
                if confidence > 0.9:
                    high_confidence_count += 1
            
            # 不再打印质量相关日志，保持静默
                        
        except Exception as e:
            self.log_message.emit("ERROR", f"分析OCR结果失败: {e}")
    
    def stop(self):
        """停止监控"""
        self.running = False
        self.log_message.emit("INFO", "监控线程停止")


class MainWindow(QMainWindow):
    """主窗口"""
    
    def __init__(self):
        super().__init__()
        
        # 初始化核心组件
        self.config_manager = ConfigManager()
        self.logger_manager = LoggerManager()
        self.ocr_service = OCRService()
        
        # 获取日志记录器
        self.logger = self.logger_manager.get_logger(__name__)
        
        # 监控线程
        self.monitor_thread = None
        
        # 状态变量
        self.is_monitoring = False
        
        self.setup_ui()
        self.setup_status_bar()
        self.setup_connections()
        
        # 程序启动时立即启动OCR服务并开始定期检查状态
        self.start_ocr_service_and_check()
        
        self.logger.info("主窗口初始化完成")
    
    def setup_ui(self):
        """初始化用户界面"""
        # 设置窗口属性
        self.setWindowTitle("富途牛牛监控 - 股票跟单软件")
        self.setGeometry(320, 0, 1200, 600)  # 窗口位置(320,0)，大小1200x600
        self.setMinimumSize(1000, 500)
        
        # 设置窗口标志，确保可以移动和调整大小
        self.setWindowFlags(Qt.Window | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | 
                           Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint)
        
        # 设置窗口图标（如果有的话）
        self.setup_window_icon()
        
        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建主布局 - 水平分割器
        main_layout = QHBoxLayout(central_widget)
        main_layout.setContentsMargins(5, 5, 5, 5)
        main_layout.setSpacing(5)
        
        # 创建水平分割器
        splitter = QSplitter(Qt.Horizontal)
        
        # 创建左侧配置面板 (70%)
        self.config_panel = ConfigPanel(self.config_manager)
        splitter.addWidget(self.config_panel)
        
        # 创建右侧日志面板 (30%)  
        self.log_panel = LogPanel(self.logger_manager)
        splitter.addWidget(self.log_panel)
        
        # 设置ConfigManager的GUI日志回调函数
        self.config_manager.gui_log_callback = self.log_panel.add_log_message
        
        # 设置分割比例 - 7:3
        splitter.setStretchFactor(0, 7)  # 左侧配置面板
        splitter.setStretchFactor(1, 3)  # 右侧日志面板
        
        # 设置初始大小
        splitter.setSizes([840, 360])  # 1200 * 0.7 : 1200 * 0.3
        
        main_layout.addWidget(splitter)
        
        self.logger.info("主界面UI初始化完成")
    
    def setup_window_icon(self):
        """设置窗口图标"""
        try:
            # 创建简单的图标
            pixmap = QPixmap(32, 32)
            pixmap.fill(QColor(0, 120, 215))  # 蓝色背景
            
            painter = QPainter(pixmap)
            painter.setPen(QColor(255, 255, 255))
            painter.setFont(QFont("Arial", 16, QFont.Bold))
            painter.drawText(pixmap.rect(), Qt.AlignCenter, "富")
            painter.end()
            
            icon = QIcon(pixmap)
            self.setWindowIcon(icon)
            
        except Exception as e:
            self.logger.warning(f"设置窗口图标失败: {e}")
    
    
    def setup_status_bar(self):
        """设置状态栏"""
        status_bar = QStatusBar()
        self.setStatusBar(status_bar)
        
        # 运行状态标签
        self.status_label = QLabel("就绪")
        status_bar.addWidget(self.status_label)
        
        # OCR服务状态
        self.ocr_status_label = QLabel("OCR: 检查中...")
        status_bar.addPermanentWidget(self.ocr_status_label)
        
        # 倒计时显示
        self.countdown_label = QLabel("等待开始...")
        self.countdown_label.setStyleSheet("font-weight: bold; color: blue;")
        status_bar.addPermanentWidget(self.countdown_label)
        
        # 当前时间
        self.time_label = QLabel()
        status_bar.addPermanentWidget(self.time_label)
        
        # 时间更新定时器
        self.time_timer = QTimer()
        self.time_timer.timeout.connect(self.update_time)
        self.time_timer.start(1000)  # 每秒更新
        
        # 倒计时相关变量
        self.start_time = None
        self.runtime_minutes = 0
        
        self.update_time()
    
    def setup_connections(self):
        """设置信号连接"""
        # 配置面板信号连接
        self.config_panel.config_changed.connect(self.on_config_changed)
        self.config_panel.start_monitoring.connect(self.start_monitoring)
        self.config_panel.stop_monitoring.connect(self.stop_monitoring)
        self.config_panel.always_on_top_changed.connect(self.on_always_on_top_changed)
        self.config_panel.trading_signal.connect(self.on_trading_signal)  # 连接交易信号
        
        # 日志面板信号连接
        self.log_panel.log_cleared.connect(self.on_logs_cleared)
    
    def start_ocr_service_and_check(self):
        """启动OCR服务并开始定期状态检查"""
        self.logger.info("🚀 程序启动，自动启动OCR服务...")
        
        # 启动OCR服务
        if self.ocr_service.ensure_service_running():
            self.logger.info("✅ OCR服务启动成功")
        else:
            self.logger.error("❌ OCR服务启动失败")
        
        # 立即检查一次状态
        self.check_ocr_service()
        
        # 设置定期检查（每30秒检查一次）
        self.ocr_check_timer = QTimer()
        self.ocr_check_timer.timeout.connect(self.check_ocr_service)
        self.ocr_check_timer.start(30000)  # 30秒间隔
        self.logger.info("📋 已设置OCR状态定期检查（30秒间隔）")

    def check_ocr_service(self):
        """检查OCR服务状态"""
        try:
            if self.ocr_service.check_service_status():
                self.ocr_status_label.setText("OCR: ✅ 正常")
                self.ocr_status_label.setStyleSheet("color: green;")
            else:
                self.ocr_status_label.setText("OCR: ❌ 未连接")
                self.ocr_status_label.setStyleSheet("color: red;")
        except Exception as e:
            self.logger.error(f"OCR状态检查异常: {e}")
            self.ocr_status_label.setText("OCR: ❌ 异常")
            self.ocr_status_label.setStyleSheet("color: red;")
    
    def update_time(self):
        """更新时间和倒计时显示"""
        current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        self.time_label.setText(current_time)
        
        # 更新倒计时
        if self.start_time and self.runtime_minutes > 0:
            elapsed = datetime.now() - self.start_time
            total_seconds = self.runtime_minutes * 60
            remaining_seconds = total_seconds - elapsed.total_seconds()
            
            if remaining_seconds > 0:
                # 格式化剩余时间
                hours = int(remaining_seconds // 3600)
                minutes = int((remaining_seconds % 3600) // 60)
                seconds = int(remaining_seconds % 60)
                
                if hours > 0:
                    countdown_text = f"剩余: {hours:02d}:{minutes:02d}:{seconds:02d}"
                else:
                    countdown_text = f"剩余: {minutes:02d}:{seconds:02d}"
                
                self.countdown_label.setText(countdown_text)
                self.countdown_label.setStyleSheet("font-weight: bold; color: blue;")
            else:
                # 时间到，停止监控
                self.countdown_label.setText("时间到！")
                self.countdown_label.setStyleSheet("font-weight: bold; color: red;")
                if self.is_monitoring:
                    self.stop_monitoring()
        elif self.is_monitoring and self.runtime_minutes == 0:
            # 持续运行模式
            self.countdown_label.setText("持续运行")
            self.countdown_label.setStyleSheet("font-weight: bold; color: green;")
        else:
            self.countdown_label.setText("等待开始...")
            self.countdown_label.setStyleSheet("font-weight: bold; color: gray;")
    
    @pyqtSlot(str, object)
    def on_config_changed(self, key, value):
        """配置变更处理"""
        self.logger.info(f"配置变更: {key}")
        
        # 更新状态栏
        if key == 'area.current_area':
            if value:
                bbox = self.config_manager.get('area.bbox')
                if bbox:
                    area_size = f"{bbox[2]-bbox[0]}×{bbox[3]-bbox[1]}"
                    self.status_label.setText(f"识别区域: {area_size}")
                else:
                    self.status_label.setText("识别区域: 已设置")
            else:
                self.status_label.setText("就绪")
    
    @pyqtSlot()
    def start_monitoring(self):
        """启动监控"""
        if self.is_monitoring:
            return
        
        try:
            # 检查OCR服务
            if not self.ocr_service.ensure_service_running():
                QMessageBox.warning(self, "服务错误", "OCR服务启动失败，无法开始监控")
                return
            
            # 获取运行时长配置
            self.runtime_minutes = self.config_manager.get('monitor.runtime_minutes', 0)
            self.start_time = datetime.now()
            
            # 创建监控线程
            self.monitor_thread = MonitorThread(self.config_manager, self.ocr_service)
            
            # 连接监控线程信号
            self.monitor_thread.log_message.connect(self.on_monitor_log)
            self.monitor_thread.ocr_result.connect(self.on_ocr_result)
            self.monitor_thread.trading_signal.connect(self.on_trading_signal)
            self.monitor_thread.finished.connect(self.on_monitor_finished)
            
            # 启动监控线程
            self.monitor_thread.start()
            
            # 更新状态
            self.is_monitoring = True
            self.status_label.setText("监控中...")
            self.ocr_status_label.setStyleSheet("color: blue;")
            
            if self.runtime_minutes > 0:
                self.logger.info(f"监控已启动，运行时长: {self.runtime_minutes} 分钟")
            else:
                self.logger.info("监控已启动，持续运行模式")
            
        except Exception as e:
            self.logger.error(f"启动监控失败: {e}")
            QMessageBox.critical(self, "错误", f"启动监控失败: {e}")
    
    @pyqtSlot()
    def stop_monitoring(self):
        """停止监控"""
        if not self.is_monitoring or not self.monitor_thread:
            return
        
        try:
            # 停止监控线程
            self.monitor_thread.stop()
            self.monitor_thread.wait(5000)  # 等待最多5秒
            
            # 重置状态
            self.is_monitoring = False
            self.start_time = None
            self.runtime_minutes = 0
            
            # 更新界面状态
            self.status_label.setText("就绪")
            self.countdown_label.setText("等待开始...")
            self.countdown_label.setStyleSheet("font-weight: bold; color: gray;")
            self.check_ocr_service()  # 重新检查OCR服务状态
            
            self.logger.info("监控已停止")
            
        except Exception as e:
            self.logger.error(f"停止监控失败: {e}")
    
    @pyqtSlot(str, str)
    def on_monitor_log(self, level, message):
        """处理监控日志"""
        # 转发到日志面板
        self.log_panel.add_log_message(level, message)
        
        # 记录到日志文件
        logger = self.logger_manager.get_logger("monitor")
        if level == "ERROR":
            logger.error(message)
        elif level == "WARNING":
            logger.warning(message)
        elif level == "SUCCESS":
            logger.info(f"✅ {message}")
        else:
            logger.info(message)
    
    @pyqtSlot(dict)
    def on_ocr_result(self, result):
        """处理OCR识别结果"""
        # 静默处理OCR结果，不打印日志
        # 更新配置面板中的市场数据
        try:
            # OCR成功时立即更新状态显示
            self.ocr_status_label.setText("OCR: ✅ 正常")
            self.ocr_status_label.setStyleSheet("color: green;")
            
            # 创建增强的OCR结果数据结构，与测试OCR保持一致
            from ocr.ocr_service import OCRService
            ocr_service = OCRService()
            enhanced_result = {
                'enhanced_data': ocr_service.extract_structured_data(result)
            }
            # 同时包含原始数据作为fallback
            enhanced_result.update(result)
            
            self.config_panel.update_market_data(enhanced_result)
        except Exception as e:
            self.logger.error(f"更新市场数据失败: {e}")
    
    @pyqtSlot(str, dict)
    def on_trading_signal(self, action, data):
        """处理交易信号"""
        # 检查是否为批量交易信号
        if action == 'BATCH' and data.get('is_batch', False):
            self.handle_batch_trading_signals(data)
            return
        
        # 单笔交易信号处理 - 打印详细的交易信息
        stock_code = data.get('stock_code', '')
        # 🔥 修复：确保所有数值字段不为None，避免格式化错误
        trading_price = data.get('trading_price') or 0
        trading_quantity = data.get('trading_quantity') or 0
        trading_amount = data.get('trading_amount') or 0
        position_change = data.get('position_change') or 0
        previous_position = data.get('previous_position') or 0
        current_position = data.get('current_position') or 0
        calculation_type = data.get('calculation_type', '')
        
        # 打印交易触发日志
        self.logger.info(f"🚨 交易信号触发: {action} {stock_code}")
        self.logger.info(f"📈 触发原因: 仓位变化 {previous_position:.2f}% → {current_position:.2f}% (差异: {position_change:+.2f}%) + 检测到\"全部成交\"")
        self.logger.info(f"💰 交易详情: {calculation_type} | 价格: ${trading_price:.2f} | 数量: {trading_quantity}股 | 金额: ${trading_amount:.2f}")
        
        # 打印计算逻辑
        account_funds = data.get('account_funds') or 3000
        if action == "买入":
            if calculation_type == "新买入":
                self.logger.info(f"📊 计算逻辑: {current_position:.2f}% × ${account_funds:,.0f} ÷ ${trading_price:.2f} = {trading_quantity}股")
            else:
                self.logger.info(f"📊 计算逻辑: ({current_position:.2f}% - {previous_position:.2f}%) × ${account_funds:,.0f} ÷ ${trading_price:.2f} = {trading_quantity}股")
        else:
            if calculation_type == "清仓":
                self.logger.info(f"📊 计算逻辑: 清仓操作，卖出全部持仓 {trading_quantity}股")
            else:
                self.logger.info(f"📊 计算逻辑: ({previous_position:.2f}% - {current_position:.2f}%) × ${account_funds:,.0f} ÷ ${trading_price:.2f} = {trading_quantity}股")
        
        # 检查是否启用自动交易
        auto_trade = self.config_manager.get('trading.auto_trade', False)
        
        if auto_trade:
            # 自动交易：直接执行
            self.logger.info(f"💰 自动执行交易: {action} {stock_code}")
            self.log_panel.add_log_message("INFO", f"💰 自动执行交易: {action} {stock_code}")
            
            # 🔥 修复：自动交易时调用富途API
            action_text = data.get('action', action)
            success, result = self.execute_futu_trade(action_text, stock_code, trading_quantity, trading_price)
            
            if success:
                # API调用成功
                self.logger.info(f"✅ 自动交易执行成功: {result.get('message', '交易完成')}")
                self.log_panel.add_log_message("INFO", f"✅ 自动交易执行成功: {result.get('message', '交易完成')}")
                
                # 打印API返回结果
                api_result_info = []
                api_result_info.append(f"订单ID: {result.get('order_id', 'N/A')}")
                api_result_info.append(f"交易状态: {result.get('status', 'N/A')}")
                api_result_info.append(f"成交价格: {result.get('executed_price', 'N/A')}")
                api_result_info.append(f"成交数量: {result.get('executed_quantity', 'N/A')}")
                api_result_info.append(f"交易时间: {result.get('trade_time', 'N/A')}")
                
                api_result_text = " | ".join(api_result_info)
                
                # 更新交易基准数据
                current_position = data.get('current_position')
                if current_position:
                    self.config_panel.update_trading_baseline_data(stock_code, current_position)
                
                # 添加到操作历史
                self.config_panel.add_history_record(
                    f"自动交易-{action}", 
                    f"{stock_code} - 市价单 × {trading_quantity}股", 
                    "success"
                )
            else:
                # API调用失败
                error_message = result.get('message', '未知错误')
                self.logger.error(f"❌ 自动交易执行失败: {error_message}")
                self.log_panel.add_log_message("ERROR", f"❌ 自动交易执行失败: {error_message}")
                
                # 🔥 新增：记录交易失败到惩罚系统
                self.config_panel.record_trade_failure(stock_code, action, error_message)
                
                # 打印API错误结果
                api_error_info = []
                api_error_info.append(f"错误代码: {result.get('error_code', 'N/A')}")
                api_error_info.append(f"错误消息: {result.get('message', 'N/A')}")
                api_error_info.append(f"详细描述: {result.get('error_desc', 'N/A')}")
                
                api_error_text = " | ".join(api_error_info)
                self.log_panel.add_log_message("ERROR", f"🔗 API错误结果: {api_error_text}")
                
                # 添加到操作历史
                self.config_panel.add_history_record(
                    f"自动交易失败-{action}", 
                    f"{stock_code} - {result.get('message', '交易失败')}", 
                    "error"
                )
        else:
            # 手动确认：弹窗提示用户
            self.logger.info(f"⏳ 等待用户确认: {action} {stock_code}")
            self.show_trading_confirmation_dialog(action, data)
    
    def handle_batch_trading_signals(self, batch_data):
        """处理批量交易信号"""
        try:
            signal_count = batch_data.get('signal_count', 0)
            stock_codes = batch_data.get('stock_codes', [])
            
            self.logger.info(f"🚨 检测到批量交易信号: {signal_count}笔交易")
            self.logger.info(f"涉及股票: {', '.join(stock_codes)}")
            
            # 检查是否启用自动交易
            auto_trade = self.config_manager.get('trading.auto_trade', False)
            
            if auto_trade:
                # 自动交易：批量执行所有交易
                self.logger.info(f"💰 自动执行批量交易: {signal_count}笔")
                self.log_panel.add_log_message("INFO", f"💰 自动执行批量交易: {signal_count}笔")
                
                # 🔥 修复：实现批量自动交易
                success_count = 0
                failed_count = 0
                
                for signal in batch_data.get('signals', []):
                    signal_action = signal['action']
                    signal_data = signal['data']
                    
                    # 执行单笔自动交易
                    stock_code = signal_data.get('stock_code', '')
                    trading_price = signal_data.get('trading_price', 0)
                    trading_quantity = signal_data.get('trading_quantity', 0)
                    action_text = signal_data.get('action', signal_action)
                    
                    self.logger.info(f"💰 执行批量交易第 {success_count + failed_count + 1} 笔: {action_text} {stock_code}")
                    
                    success, result = self.execute_futu_trade(action_text, stock_code, trading_quantity, trading_price)
                    
                    if success:
                        success_count += 1
                        self.logger.info(f"✅ 批量交易成功: {stock_code}")
                        self.log_panel.add_log_message("INFO", f"✅ 批量交易成功: {stock_code}")
                        
                        # 更新交易基准数据
                        current_position = signal_data.get('current_position')
                        if current_position:
                            self.config_panel.update_trading_baseline_data(stock_code, current_position)
                    else:
                        failed_count += 1
                        self.logger.error(f"❌ 批量交易失败: {stock_code} - {result.get('message', '未知错误')}")
                        self.log_panel.add_log_message("ERROR", f"❌ 批量交易失败: {stock_code} - {result.get('message', '未知错误')}")
                
                # 添加到操作历史
                if failed_count == 0:
                    self.config_panel.add_history_record(
                        f"批量自动交易", 
                        f"{signal_count}笔交易全部成功 - 股票: {', '.join(stock_codes)}", 
                        "success"
                    )
                else:
                    self.config_panel.add_history_record(
                        f"批量自动交易", 
                        f"{success_count}笔成功，{failed_count}笔失败 - 股票: {', '.join(stock_codes)}", 
                        "warning"
                    )
            else:
                # 手动确认：显示批量交易确认弹窗
                self.show_batch_trading_confirmation_dialog(batch_data)
                
        except Exception as e:
            self.logger.error(f"处理批量交易信号失败: {e}")
    
    def show_trading_confirmation_dialog(self, action, data):
        """显示交易确认对话框"""
        try:
            from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTextEdit
            
            dialog = QDialog(self)
            dialog.setWindowTitle("交易信号确认")
            dialog.setModal(True)
            dialog.resize(500, 400)
            
            layout = QVBoxLayout(dialog)
            
            # 标题
            title_label = QLabel("🚨 检测到交易信号")
            title_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #d73027; margin-bottom: 10px;")
            layout.addWidget(title_label)
            
            # 交易基本信息
            info_layout = QVBoxLayout()
            
            stock_code = data.get('stock_code', '')
            action_text = data.get('action', action)
            trading_price = data.get('trading_price', 0)
            trading_quantity = data.get('trading_quantity', 0) 
            trading_amount = data.get('trading_amount', 0)
            price_source = data.get('price_source', '')
            position_change = data.get('position_change', 0)
            is_full_sale = data.get('is_full_sale', False)
            
            signal_label = QLabel(f"📊 交易类型: {action_text}")
            signal_label.setStyleSheet("font-size: 14px; font-weight: bold; color: #0066cc; margin: 5px 0;")
            info_layout.addWidget(signal_label)
            
            stock_label = QLabel(f"🏷️  股票代码: {stock_code}")
            stock_label.setStyleSheet("font-size: 12px; color: #333333; margin: 3px 0;")
            info_layout.addWidget(stock_label)
            
            # 触发原因 - 显示前后仓位对比和"部成交"条件
            previous_position = data.get('previous_position')
            current_position = data.get('current_position')
            position_change = data.get('position_change') or 0
            
            if previous_position is not None and current_position is not None:
                trigger_reason = f"仓位变化: {previous_position:.2f}% → {current_position:.2f}% (差异: {position_change:+.2f}%) + 检测到\"全部成交\""
            else:
                trigger_reason = f"仓位变化: {position_change:+.2f}% + 检测到\"全部成交\""
                
            if is_full_sale:
                trigger_reason += " (清仓)"
            
            reason_label = QLabel(f"📈 触发原因: {trigger_reason}")
            reason_label.setStyleSheet("font-size: 12px; color: #333333; margin: 3px 0;")
            info_layout.addWidget(reason_label)
            
            # 交易详情
            price_label = QLabel(f"💰 交易价格: ${trading_price:.2f} ({price_source})")
            price_label.setStyleSheet("font-size: 12px; color: #333333; margin: 3px 0;")
            info_layout.addWidget(price_label)
            
            # 🔥 修复：交易数量统一显示正数
            display_quantity = abs(trading_quantity) if trading_quantity else 0
            quantity_label = QLabel(f"📦 交易数量: {display_quantity} 股")
            quantity_label.setStyleSheet("font-size: 12px; color: #333333; margin: 3px 0;")
            info_layout.addWidget(quantity_label)
            
            # 交易数量计算逻辑
            account_funds = data.get('account_funds', 3000)  # 获取实际账户资金
            quantity_calculation = data.get('quantity_calculation', '')
            if quantity_calculation:
                quantity_calc_label = QLabel(f"📊 数量计算: {quantity_calculation}")
                quantity_calc_label.setStyleSheet("font-size: 11px; color: #666666; font-style: italic; margin: 2px 0;")
                info_layout.addWidget(quantity_calc_label)
            
            # 🔥 修复：交易金额统一显示正数
            display_amount = abs(trading_amount) if trading_amount else 0
            amount_label = QLabel(f"💵 交易金额: ${display_amount:.2f}")
            amount_label.setStyleSheet("font-size: 13px; font-weight: bold; color: #0066cc; margin: 5px 0;")
            info_layout.addWidget(amount_label)
            
            # 详细计算信息显示
            calculation_type = data.get('calculation_type', '')
            monitor_position = data.get('monitor_position') or 0
            own_position = data.get('own_position') or 0
            
            if calculation_type:
                calc_info_label = QLabel(f"📊 交易类型: {calculation_type}")
                calc_info_label.setStyleSheet("font-size: 11px; color: #666666; font-weight: bold; margin: 3px 0;")
                info_layout.addWidget(calc_info_label)
                
                # 🔥 修复：显示实际的仓位变化对比
                if previous_position is not None and current_position is not None:
                    position_info_label = QLabel(f"📈 仓位对比: {previous_position:.2f}% → {current_position:.2f}% (差异: {abs(previous_position-current_position):.2f}%)")
                else:
                    position_info_label = QLabel(f"📈 仓位对比: 监控组合 {monitor_position:.2f}% → 自有组合 {own_position:.2f}%")
                position_info_label.setStyleSheet("font-size: 10px; color: #666666; margin: 2px 0;")
                info_layout.addWidget(position_info_label)
            
            # 🔥 修复：使用实际的仓位变化数据显示计算公式
            monitor_cost_price = data.get('monitor_cost_price', 0)
            own_market_price = data.get('own_market_price', 0)
            
            # 使用实际的仓位变化数据
            actual_previous = previous_position if previous_position is not None else 0
            actual_current = current_position if current_position is not None else 0
            actual_diff = abs(actual_previous - actual_current)
            
            if action_text == "买入":
                if calculation_type == "新买入":
                    logic_text = f"📊 具体计算: {actual_current:.2f}% × ${account_funds:,.0f} ÷ ${monitor_cost_price:.2f} = {display_quantity} 股"
                    detail_text = f"   ➤ 仓位比例 × 账户资金 ÷ 监控成本价 = 买入数量"
                else:
                    logic_text = f"📊 具体计算: ({actual_current:.2f}% - {actual_previous:.2f}%) × ${account_funds:,.0f} ÷ ${own_market_price:.2f} = {display_quantity} 股"
                    detail_text = f"   ➤ 仓位差异 × 账户资金 ÷ 自有市价 = 加仓数量"
            else:
                if calculation_type == "清仓":
                    own_holding_qty = data.get('own_holding_quantity', abs(trading_quantity))
                    logic_text = f"📊 具体计算: 全部持仓 {own_holding_qty} 股 → 卖出 {display_quantity} 股"
                    detail_text = f"   ➤ 清仓操作：卖出全部持有数量"
                else:
                    logic_text = f"📊 具体计算: ({actual_previous:.2f}% - {actual_current:.2f}%) × ${account_funds:,.0f} ÷ ${own_market_price:.2f} = {display_quantity} 股"
                    detail_text = f"   ➤ 仓位差异 × 账户资金 ÷ 自有市价 = 减仓数量"
            
            logic_label = QLabel(logic_text)
            logic_label.setStyleSheet("font-size: 11px; color: #0066cc; font-weight: bold; margin: 3px 0;")
            info_layout.addWidget(logic_label)
            
            detail_label = QLabel(detail_text)
            detail_label.setStyleSheet("font-size: 10px; color: #888888; font-style: italic; margin: 1px 0;")
            info_layout.addWidget(detail_label)
            
            layout.addLayout(info_layout)
            
            # 询问框
            question_label = QLabel("⚠️ 是否确认执行此次交易？")
            question_label.setStyleSheet("font-size: 14px; font-weight: bold; color: #d73027; margin: 15px 0 10px 0;")
            layout.addWidget(question_label)
            
            # 按钮区域
            button_layout = QHBoxLayout()
            
            # 确认按钮
            confirm_btn = QPushButton("✅ 确认交易")
            confirm_btn.setStyleSheet("""
                QPushButton {
                    background-color: #4CAF50;
                    color: white;
                    font-weight: bold;
                    padding: 10px 20px;
                    border: none;
                    border-radius: 5px;
                }
                QPushButton:hover {
                    background-color: #45a049;
                }
            """)
            confirm_btn.clicked.connect(lambda: self.confirm_trade_dialog(dialog, action, data))
            button_layout.addWidget(confirm_btn)
            
            # 取消按钮
            cancel_btn = QPushButton("❌ 取消交易")
            cancel_btn.setStyleSheet("""
                QPushButton {
                    background-color: #f44336;
                    color: white;
                    font-weight: bold;
                    padding: 10px 20px;
                    border: none;
                    border-radius: 5px;
                }
                QPushButton:hover {
                    background-color: #da190b;
                }
            """)
            cancel_btn.clicked.connect(lambda: self.cancel_trade_dialog(dialog, action, data))
            button_layout.addWidget(cancel_btn)
            
            layout.addLayout(button_layout)
            
            # 显示对话框
            dialog.exec_()
            
        except Exception as e:
            self.logger.error(f"显示交易确认对话框失败: {e}")
    

    def cancel_trade_dialog(self, dialog, action, data):
        """取消交易对话框"""
        try:
            stock_code = data.get('stock_code', '')
            self.logger.info(f"👤 用户取消交易: {action} {stock_code}")
            
            # 🔥 关键修复：删除pending状态的交易记录
            if stock_code:
                self.config_panel.remove_latest_pending_trade_record(action, stock_code)
            
            dialog.close()
        except Exception as e:
            self.logger.error(f"取消交易对话框失败: {e}")
            # 即使出错也要确保对话框关闭
            try:
                dialog.close()
            except:
                pass
    
    def confirm_trade_dialog(self, dialog, action, data):
        """确认交易对话框"""
        try:
            stock_code = data.get('stock_code', '')
            trading_price = data.get('trading_price', 0)
            trading_quantity = data.get('trading_quantity', 0)
            
            self.logger.info(f"👤 用户确认交易: {action} {stock_code}")
            dialog.close()
            
            # 执行富途交易API调用
            self.logger.info(f"📈 开始执行交易: {action} {stock_code} - 数量:{trading_quantity}股 市价单")
            self.log_panel.add_log_message("INFO", f"📈 开始执行交易: {action} {stock_code} - 数量:{trading_quantity}股 市价单")
            
            # 调用富途交易API
            success, result = self.execute_futu_trade(action, stock_code, trading_quantity, trading_price)
            
            if success:
                self.logger.info(f"✅ 交易执行成功: {result.get('message', '交易完成')}")
                
                # 🔥 修复：将API返回结果打印在日志区域（只打印关键结果，不是原始响应）
                if 'order_id' in result:
                    self.log_panel.add_log_message("INFO", f"📋 订单ID: {result['order_id']}")
                
                # 打印API返回的关键信息到日志区域
                api_result_info = []
                api_result_info.append(f"订单ID: {result.get('order_id', 'N/A')}")
                api_result_info.append(f"交易状态: {result.get('status', 'N/A')}")
                api_result_info.append(f"成交价格: {result.get('executed_price', 'N/A')}")
                api_result_info.append(f"成交数量: {result.get('executed_quantity', 'N/A')}")
                api_result_info.append(f"交易时间: {result.get('trade_time', 'N/A')}")
                
                api_result_text = " | ".join(api_result_info)
                self.log_panel.add_log_message("INFO", f"🔗 API返回结果: {api_result_text}")
                
                # 同时记录到控制台日志
                self.logger.info(f"🔗 API返回结果: {api_result_text}")
                
                # 更新操作历史状态（从pending改为success）
                self.config_panel.update_latest_trade_record_status(
                    f"手动交易-{action}", 
                    f"{stock_code} - 市价单 × {trading_quantity}股", 
                    "success"
                )
                
                # 🔥 关键修复：交易成功后更新该股票的交易基准
                self.logger.info(f"🔄 交易确认成功，更新 {stock_code} 的交易基准...")
                
                # 获取当前该股票的仓位比例
                current_position = None
                if hasattr(self.config_panel, 'market_data_list'):
                    for item in self.config_panel.market_data_list:
                        if item.get('代码') == stock_code:
                            current_position = item.get('仓位比例')
                            break
                
                if current_position:
                    self.config_panel.update_trading_baseline_data(stock_code, current_position)
                else:
                    self.logger.warning(f"⚠️ 未找到 {stock_code} 的当前仓位数据，无法更新基准")
            else:
                error_message = result.get('message', '未知错误')
                self.logger.error(f"❌ 交易执行失败: {error_message}")
                
                # 🔥 新增：记录交易失败到惩罚系统
                self.config_panel.record_trade_failure(stock_code, action, error_message)
                
                # 🔥 修复：打印API失败返回的关键信息到GUI日志区域
                api_error_info = []
                api_error_info.append(f"错误代码: {result.get('error_code', 'N/A')}")
                api_error_info.append(f"错误消息: {result.get('message', 'N/A')}")
                api_error_info.append(f"详细描述: {result.get('error_desc', 'N/A')}")
                
                api_error_text = " | ".join(api_error_info)
                self.log_panel.add_log_message("ERROR", f"🔗 API错误结果: {api_error_text}")
                
                # 同时记录到控制台日志
                self.logger.error(f"🔗 API错误结果: {api_error_text}")
                
                # 更新操作历史状态（从pending改为error）
                self.config_panel.update_latest_trade_record_status(
                    f"交易失败-{action}", 
                    f"{stock_code} - {result.get('message', '交易失败')}", 
                    "error"
                )
            
        except Exception as e:
            self.logger.error(f"确认交易对话框失败: {e}")
            # 即使出错也要确保对话框关闭
            try:
                dialog.close()
            except:
                pass
    
    def execute_futu_trade(self, action, stock_code, quantity, price):
        """执行富途交易API调用"""
        try:
            # 🔥 增加日志确认API调用
            self.logger.info(f"🔗 正在调用富途API: {action} {stock_code} 数量:{quantity} 价格:{price}")
            self.log_panel.add_log_message("INFO", f"🔗 正在调用富途API: {action} {stock_code} 数量:{quantity} 价格:{price}")
            
            # 🔥 修复：从配置面板获取交易密码
            trading_password = self.config_panel.password_edit.text().strip()
            if not trading_password:
                return False, {"message": "请输入交易密码"}
            
            self.logger.info(f"🔐 已获取交易密码，长度: {len(trading_password)}")
            self.log_panel.add_log_message("INFO", f"🔐 已获取交易密码，长度: {len(trading_password)}")
            
            # 导入富途交易模块
            from trading.futu_trader import FutuTrader
            
            # 创建富途交易实例
            futu_trader = FutuTrader(self.config_manager)
            
            # 连接富途API
            if not futu_trader.connect():
                return False, {"message": "无法连接富途API"}
            
            # 转换股票代码格式 (BABA -> US.BABA)
            futu_code = self.convert_to_futu_code(stock_code)
            
            # 根据动作执行对应的交易 - 🔥 修复：使用市价单（price=None）
            if action.upper() in ["买入", "BUY"]:
                result = futu_trader.buy_stock(futu_code, quantity, None, trading_password)  # 市价单
            elif action.upper() in ["卖出", "SELL"]:
                result = futu_trader.sell_stock(futu_code, quantity, None, trading_password)  # 市价单
            else:
                return False, {"message": f"未知的交易动作: {action}"}
            
            # 返回交易结果
            success = result.get('success', False)
            return success, result
            
        except Exception as e:
            self.logger.error(f"执行富途交易失败: {e}")
            self.log_panel.add_log_message("ERROR", f"执行富途交易失败: {e}")
            return False, {"message": f"交易执行异常: {e}"}
    
    def convert_to_futu_code(self, stock_code):
        """将股票代码转换为富途API格式"""
        try:
            # 如果已经是富途格式，直接返回
            if '.' in stock_code:
                return stock_code
            
            # 美股代码转换 (AAPL -> US.AAPL)
            # 这里假设监控的都是美股，可以根据需要扩展支持港股等
            futu_code = f"US.{stock_code}"
            self.logger.info(f"🔄 股票代码转换: {stock_code} -> {futu_code}")
            return futu_code
            
        except Exception as e:
            self.logger.error(f"股票代码转换失败: {e}")
            # 出错时返回原代码
            return stock_code
    
    def show_batch_trading_confirmation_dialog(self, batch_data):
        """显示批量交易确认对话框"""
        try:
            from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTextEdit, QScrollArea, QWidget
            
            signal_count = batch_data.get('signal_count', 0)
            stock_codes = batch_data.get('stock_codes', [])
            signals = batch_data.get('signals', [])
            primary_signal = batch_data.get('primary_signal', {})
            
            dialog = QDialog(self)
            dialog.setWindowTitle("批量交易信号确认")
            dialog.setModal(True)
            dialog.resize(600, 500)
            
            layout = QVBoxLayout(dialog)
            
            # 标题
            title_label = QLabel(f"🚨 检测到 {signal_count} 笔交易信号")
            title_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #d73027; margin-bottom: 10px;")
            layout.addWidget(title_label)
            
            # 批量交易汇总信息
            summary_layout = QVBoxLayout()
            
            summary_label = QLabel(f"📊 本次涉及股票: {', '.join(stock_codes)}")
            summary_label.setStyleSheet("font-size: 14px; font-weight: bold; color: #0066cc; margin: 5px 0;")
            summary_layout.addWidget(summary_label)
            
            count_label = QLabel(f"📈 交易笔数: {signal_count} 笔")
            count_label.setStyleSheet("font-size: 12px; color: #333333; margin: 3px 0;")
            summary_layout.addWidget(count_label)
            
            layout.addLayout(summary_layout)
            
            # 分隔线
            separator = QLabel("─" * 50)
            separator.setStyleSheet("color: #cccccc; margin: 10px 0;")
            layout.addWidget(separator)
            
            # 第一笔交易的详细信息（主要信息）
            detail_label = QLabel("📋 第一笔交易详情:")
            detail_label.setStyleSheet("font-size: 14px; font-weight: bold; color: #333333; margin: 10px 0 5px 0;")
            layout.addWidget(detail_label)
            
            # 显示第一笔交易的详细信息
            self.add_primary_signal_details(layout, primary_signal)
            
            # 其他交易概要
            if signal_count > 1:
                other_label = QLabel(f"📝 其他 {signal_count - 1} 笔交易:")
                other_label.setStyleSheet("font-size: 12px; font-weight: bold; color: #666666; margin: 10px 0 5px 0;")
                layout.addWidget(other_label)
                
                # 创建滚动区域显示其他交易
                scroll_area = QScrollArea()
                scroll_widget = QWidget()
                scroll_layout = QVBoxLayout(scroll_widget)
                
                for i, signal in enumerate(signals[1:], 2):  # 从第二笔开始
                    signal_data = signal['data']
                    summary_text = f"{i}. {signal_data['stock_code']} {signal_data['action']} ${signal_data['trading_amount']:.2f}"
                    summary_item = QLabel(summary_text)
                    summary_item.setStyleSheet("font-size: 11px; color: #666666; margin: 2px 0; padding: 2px;")
                    scroll_layout.addWidget(summary_item)
                
                scroll_area.setWidget(scroll_widget)
                scroll_area.setMaximumHeight(100)
                scroll_area.setWidgetResizable(True)
                layout.addWidget(scroll_area)
            
            # 询问框
            question_label = QLabel(f"⚠️ 是否确认执行这 {signal_count} 笔交易？")
            question_label.setStyleSheet("font-size: 14px; font-weight: bold; color: #d73027; margin: 15px 0 10px 0;")
            layout.addWidget(question_label)
            
            # 按钮区域
            button_layout = QHBoxLayout()
            
            # 确认按钮
            confirm_btn = QPushButton("确认执行")
            confirm_btn.setStyleSheet("""
                QPushButton {
                    background-color: #28a745;
                    color: white;
                    font-weight: bold;
                    padding: 8px 16px;
                    border: none;
                    border-radius: 4px;
                }
                QPushButton:hover {
                    background-color: #218838;
                }
            """)
            confirm_btn.clicked.connect(lambda: self.handle_batch_trading_execution(batch_data, dialog))
            button_layout.addWidget(confirm_btn)
            
            # 取消按钮
            cancel_btn = QPushButton("取消")
            cancel_btn.setStyleSheet("""
                QPushButton {
                    background-color: #dc3545;
                    color: white;
                    font-weight: bold;
                    padding: 8px 16px;
                    border: none;
                    border-radius: 4px;
                }
                QPushButton:hover {
                    background-color: #c82333;
                }
            """)
            cancel_btn.clicked.connect(dialog.reject)
            button_layout.addWidget(cancel_btn)
            
            layout.addLayout(button_layout)
            
            # 显示对话框
            dialog.exec_()
            
        except Exception as e:
            self.logger.error(f"显示批量交易确认对话框失败: {e}")
            from PyQt5.QtWidgets import QMessageBox
            QMessageBox.warning(self, "错误", f"显示批量交易确认对话框失败: {e}")
    
    def add_primary_signal_details(self, layout, primary_signal):
        """添加主要交易信号的详细信息到布局中"""
        info_layout = QVBoxLayout()
        
        stock_code = primary_signal.get('stock_code', '')
        action_text = primary_signal.get('action', '')
        trading_price = primary_signal.get('trading_price') or 0
        trading_quantity = primary_signal.get('trading_quantity') or 0
        trading_amount = primary_signal.get('trading_amount') or 0
        price_source = primary_signal.get('price_source', '')
        position_change = primary_signal.get('position_change') or 0
        is_full_sale = primary_signal.get('is_full_sale', False)
        previous_position = primary_signal.get('previous_position')
        current_position = primary_signal.get('current_position')
        
        # 基本信息（紧凑显示）
        stock_label = QLabel(f"🏷️ {stock_code} {action_text}")
        stock_label.setStyleSheet("font-size: 13px; font-weight: bold; color: #0066cc; margin: 2px 0;")
        info_layout.addWidget(stock_label)
        
        # 仓位对比
        if previous_position is not None and current_position is not None:
            position_text = f"📈 仓位: {previous_position:.2f}% → {current_position:.2f}% (差异: {position_change:+.2f}%)"
        else:
            position_text = f"📈 仓位变化: {position_change:+.2f}%"
        if is_full_sale:
            position_text += " (清仓)"
            
        position_label = QLabel(position_text)
        position_label.setStyleSheet("font-size: 11px; color: #333333; margin: 1px 0;")
        info_layout.addWidget(position_label)
        
        # 交易信息（一行显示）
        trade_info = f"💰 ${trading_price:.2f} × {trading_quantity}股 = ${trading_amount:.2f}"
        trade_label = QLabel(trade_info)
        trade_label.setStyleSheet("font-size: 11px; color: #333333; margin: 1px 0;")
        info_layout.addWidget(trade_label)
        
        layout.addLayout(info_layout)
    
    def handle_batch_trading_execution(self, batch_data, dialog):
        """处理批量交易执行"""
        try:
            # 关闭对话框
            dialog.accept()
            
            # 执行批量交易
            signal_count = batch_data.get('signal_count', 0)
            stock_codes = batch_data.get('stock_codes', [])
            
            self.logger.info(f"💰 用户确认执行批量交易: {signal_count}笔")
            # TODO: 实现具体的富途批量交易API调用
            
            # 添加到操作历史
            self.config_panel.add_history_record(
                f"批量交易确认",
                f"{signal_count}笔交易 - 股票: {', '.join(stock_codes)}",
                "success"
            )
            
            # 显示成功提示
            from PyQt5.QtWidgets import QMessageBox
            QMessageBox.information(self, "交易确认", f"已确认执行 {signal_count} 笔交易")
            
        except Exception as e:
            self.logger.error(f"处理批量交易执行失败: {e}")
    
    @pyqtSlot()
    def on_monitor_finished(self):
        """监控线程结束处理"""
        self.is_monitoring = False
        self.status_label.setText("就绪")
    
    @pyqtSlot()
    def on_logs_cleared(self):
        """日志清空处理"""
        self.logger.info("日志已清空")
    
    @pyqtSlot(bool)
    def on_always_on_top_changed(self, checked):
        """处理窗口置顶状态变更"""
        try:
            if checked:
                # 设置窗口置顶
                self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
                self.logger.info("✅ 窗口置顶已开启")
            else:
                # 取消窗口置顶
                self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
                self.logger.info("❌ 窗口置顶已关闭")
            
            # 重新显示窗口（修改flags后需要重新显示）
            self.show()
            
        except Exception as e:
            self.logger.error(f"切换窗口置顶状态失败: {e}")
    
    
    def closeEvent(self, event):
        """窗口关闭事件"""
        if self.is_monitoring:
            reply = QMessageBox.question(
                self, '确认退出',
                '监控正在运行中，确定要退出吗？',
                QMessageBox.Yes | QMessageBox.No
            )
            
            if reply == QMessageBox.No:
                event.ignore()
                return
            
            # 停止监控
            self.stop_monitoring()
        
        # 保存配置
        self.config_manager.auto_save()
        
        # 记录退出日志
        self.logger.info("应用程序正常退出")
        
        event.accept()


def main():
    """主函数"""
    app = QApplication(sys.argv)
    app.setApplicationName("富途牛牛监控")
    app.setApplicationVersion("1.0.0")
    
    # 设置应用样式
    app.setStyleSheet("""
        QMainWindow {
            background-color: #f5f5f5;
        }
        QGroupBox {
            font-weight: bold;
            border: 2px solid #cccccc;
            border-radius: 5px;
            margin-top: 1ex;
            padding-top: 10px;
        }
        QGroupBox::title {
            subcontrol-origin: margin;
            left: 10px;
            padding: 0 5px 0 5px;
        }
        QPushButton {
            padding: 5px 10px;
            border: 1px solid #cccccc;
            border-radius: 3px;
            background-color: #ffffff;
        }
        QPushButton:hover {
            background-color: #e6e6e6;
        }
        QPushButton:pressed {
            background-color: #cccccc;
        }
    """)
    
    # 创建主窗口
    window = MainWindow()
    window.show()
    
    # 运行应用
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
